################################################################################
# File: models.py
# Package: itacqos.uddi
# Author: Vincent Pretre
# Last update: $LastChangedDate$
################################################################################

## @package itacqos.uddi.models
#
# This module describes the database used by iTaC-QoS. Thanks to Django and its MVC design, each table is represented as a class of
# this module.

from django.db import models
from django.contrib.auth.models import User

## Defines a web service vendor.
class Vendor(models.Model):
	## Name of the vendor.
	# Note: his name is not his login. The login is handled by the user attribute
	name = models.CharField(max_length = 100, unique = True)
	## User linked to the vendor.
	# In order to avoid security problems, we chose to let Django handle authentication. 
	# For this reason, each Vendor is linked to a User (auth.User)
	user = models.ForeignKey(User)
	## Vendor's website.
	webSite = models.URLField()
	## A description of the Vendor.
	# Tis description can be a description of the company for example.
	desc = models.TextField()
	
	## Displays vendor's name when printing.
	# @param self Pointer to the instance
	# See Django's help about the unicode function: http://docs.djangoproject.com/en/dev/ref/models/instances/#unicode
	def __unicode__(self):
		return self.name

## Defines a web service category.
#
# Those categories helps site's navigation.
class Category(models.Model):
	## Name of the category.
	name = models.CharField(max_length = 100)
	## Slug of the category.
	# The slug is used when the category is in the URL. The slug is calculated from the name:
	# - all letter are lower
	# - special character are removed
	# - accuented letters a re replaced by classical letters
	# - spaces are replaced by dash ...
	# See "slugify" in Django's template help: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#slugify
	slug = models.SlugField()
	
	## Displays category's name when printing.
	# @param self Pointer to the instance
	# See Django's help about the unicode function: http://docs.djangoproject.com/en/dev/ref/models/instances/#unicode
	def __unicode__(self):
		return self.name

## Defines a web service keyword.
class Keyword(models.Model):
	## Name of the keyword.
	name = models.CharField(max_length = 100)
	## Slug of the keyword.
	# The slug is used when the category is in the URL. The slug is calculated from the name:
	# - all letter are lower
	# - special character are removed
	# - accuented letters a re replaced by classical letters
	# - spaces are replaced by dash ...
	# See "slugify" in Django's template help: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#slugify
	slug = models.SlugField()
	
	## Displays keyword's name when printing.
	# @param self Pointer to the instance
	# See Django's help about the unicode function: http://docs.djangoproject.com/en/dev/ref/models/instances/#unicode
	def __unicode__(self):
		return self.name

## Defines a web service.
class WebService(models.Model):
	## Name of the web service.
	name = models.CharField(max_length = 100, verbose_name="Name")
	## A textual description of the service.
	# We prefered to use a TextField to allow long description with paragraphs etc.
	desc = models.TextField(verbose_name="Description")
	## The web service's vendor.
	producedBy = models.ForeignKey(Vendor)
	
	## The URL where the service can be accessed.
	url = models.URLField(verbose_name="URL")
	## The WSDL file of the service.
	# In general, this value is equal to URL?wsdl, but we do not set it automatically to handle
	# particular cases.
	wsdl = models.URLField(verbose_name="WSDL file")
	## The path to the folder containing all files linked to the service.
	# Those files are:
	# - a copy of the WSDL file (name.wsdl)
	# - the UML model (model.xmi)
	# - tests generated by TD in XML (tests.xml)
	# - a subfolder containing Java tests (tests/)
	# - maybe others ;)
	# @todo Complete list of files linked to a service.
	dir = models.CharField(max_length = 300, blank = True)
	
	## Tells if the service is visible on the site.
	public = models.BooleanField(blank=True, verbose_name="Show to customers")
	## Percentage of tests which obtained a "success" verdict.
	# This information is redundant, but we do not want to compute that every time we have to
	# display this information.
	percentageOfSuccessfulTests = models.FloatField(blank = True)
	
	## The list of categories the service belongs to.
	categories = models.ManyToManyField(Category, blank=True, verbose_name="Categories")
	## The list of keywords linked to the service.
	keywords = models.ManyToManyField(Keyword, blank=True, verbose_name="Keywords")

	## Displays web service's name when printing.
	# @param self Pointer to the instance
	# See Django's help about the unicode function: http://docs.djangoproject.com/en/dev/ref/models/instances/#unicode
	def __unicode__(self):
		return self.name

## Defines a web service's operation.
class Operation(models.Model):
	## Name of the operation, as defined in the WSDL file.
	name = models.CharField(max_length = 100)
	## Web service which owns the operation.
	belongsTo = models.ForeignKey(WebService)
	## Operations on which the operation relies.
	# There is two type of relations between web service's operations:
	# - composition :  the operation acts as a client of another operation
	# - temporal dependency : the operation can only be called if another one has been called previously (for example login and register)
	# In the model, we only describe direct dependency. That means that if an operation 'a' relies on an operation 'b' and this one relies
	# on an operation 'c', 'c' will not appear in 'a' dependency.
	# Indirect relations are computed by itacqos.uddi.views.common.getDependencies().
	reliesOn = models.ManyToManyField('self', symmetrical = False)
	
	## Displays operation's name when printing.
	# @param self Pointer to the instance
	# See Django's help about the unicode function: http://docs.djangoproject.com/en/dev/ref/models/instances/#unicode
	def __unicode__(self):
		return self.name

## Defines test categories.
# For the moment, there exists four categories:
# - FIA: tests about identification and anthentication
# - FPR: tests about customers' privacy (name, address ...)
# - FDP: tets about users' data privacy
# - FCT: tests about the web service bussiness functionnalities.
class TestCategory(models.Model):
	## Abbreviation of the category.
	abbr = models.CharField(max_length = 5, unique = True)
	## Complete name of the category.
	name = models.CharField(max_length = 100, unique = True)
	## A complete description of the category.
	desc = models.TextField()
	## Tells if the category has been accepted by the site's administrator.
	# If a new category is discovered in a model, it is added to the list. It has to be validated by an administrator
	# to be displayed in the site.
	adminValidated = models.BooleanField()

	## Displays category's abbreviation and name when printing.
	# @param self Pointer to the instance
	# See Django's help about the unicode function: http://docs.djangoproject.com/en/dev/ref/models/instances/#unicode
	def __unicode__(self):
		return self.abbr + " - " + self.name

## Defines results that can be obtained by a test.
# There exists five possible verdicts:
# - passed: when a test succeeds
# - incomplete passed: when some expected data are not provided
# - safe failed: when a tests fails without comprimising service's security (a wrong error is returned or an error is produced when a result was expected)
# - failed: when the service produces bad results
# - critical failed: when the test discovers a security leak (a result is produced when an error was expected)
class Verdict(models.Model):
	## Identifier of the verdict.
	id = models.IntegerField(primary_key = True)
	## Name of the verdict.
	# See class description for the list of names.
	name = models.CharField(max_length = 50)

	## Displays verdict's name when printing.
	# @param self Pointer to the instance
	# See Django's help about the unicode function: http://docs.djangoproject.com/en/dev/ref/models/instances/#unicode
	def __unicode__(self):
		return self.name

## Defines a test
class Test(models.Model):
	## Test's name, as created by the test tool.
	name = models.CharField(max_length = 100)
	## Tested operation/
	operation = models.ForeignKey(Operation)
	## Test's category.
	category = models.ManyToManyField(TestCategory)
	## Result obtained.
	verdict = models.ForeignKey(Verdict)

	## Displays test's name when printing.
	# @param self Pointer to the instance
	# See Django's help about the unicode function: http://docs.djangoproject.com/en/dev/ref/models/instances/#unicode
	def __unicode__(self):
		return self.name

## Defines number of tests passed in each category by a service.
# This is a redundant information but is used to accelerate display of marks.
class ServiceResultPercentage(models.Model):
	## The concerned service.
	service = models.ForeignKey(WebService)
	## The test category.
	testCat = models.ForeignKey(TestCategory)
	## The percentage of tests which passed.
	percentage = models.FloatField()